home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 June / Amiga Games Extra 1996 #6.iso / userbox / publicdomain / cuckoo / source / playsound.c < prev    next >
C/C++ Source or Header  |  1993-10-06  |  6KB  |  218 lines

  1. /*****************************************************************************
  2.  * PlaySound.c
  3.  * This routine sets up an ioRequest and plays back a waveform through the
  4.  * Amiga audio hardware
  5.  *
  6.  * Usage : PlaySound(buffer,repeat,period,volume)
  7.  * buffer is a pointer to a waveform
  8.  * repeat is the number of times to play the wave (0 == forever)
  9.  * period determines the playback rate (minimum value == 124)
  10.  * volume goes from 0 to 64
  11.  *****************************************************************************/
  12.  
  13. #include "exec/types.h"
  14. #include "devices/audio.h"
  15. #include "exec/memory.h"
  16.  
  17. #define LEFT0F    1
  18. #define RIGHT0F 2
  19. #define RIGHT1F 4
  20. #define LEFT1F    8
  21. #define SIGBREAKF_CTRL_C (1<<12)
  22.  
  23. extern struct MsgPort *CreatePort();
  24. struct IOAudio *AllocMem();
  25.  
  26. /* Look for a left channel, then a right */
  27. UBYTE allocationMap[] = { LEFT0F, LEFT1F, RIGHT0F, RIGHT1F };
  28.  
  29. /*****************************************************************************
  30.  * Purpose: To allocate and initialize an IO Request Block.             *
  31.  *****************************************************************************/
  32.  
  33. SetIOA(per, vol, repeat, len, ioa)
  34. LONG per, vol, repeat;
  35. ULONG len;
  36. struct IOAudio **ioa;
  37. {
  38.     struct MsgPort *port;
  39.  
  40.     /* Allocate IOAudio structure */
  41.     (*ioa) = AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);
  42.  
  43.     /* If Allocation Successful ... */
  44.     if (*ioa)
  45.     {
  46.     /* Set Priority */
  47.     (*ioa)->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
  48.     /* Create Message port for IORequest to talk to Amiga */
  49.     if (!(port = CreatePort(NULL, 0)))
  50.     {
  51.         FreeMem((*ioa), sizeof(struct IOAudio));
  52.         *ioa = NULL;
  53.     }
  54.     /* If Creation Successful ... */
  55.     else
  56.     {
  57.         /* Get a channel */
  58.         (*ioa)->ioa_Request.io_Message.mn_ReplyPort = port;
  59.         (*ioa)->ioa_Data = allocationMap;
  60.         (*ioa)->ioa_Length = sizeof(allocationMap);
  61.         /* Open Audio Device for output */
  62.         if(OpenDevice(AUDIONAME, 0, (*ioa), 0))
  63.         {
  64.         DeletePort(port);
  65.         FreeMem((*ioa), sizeof(struct IOAudio));
  66.         *ioa = NULL;
  67.         }
  68.         /* If open worked ... */
  69.         else
  70.         {
  71.         /* Set Up Request */
  72.         (*ioa)->ioa_Request.io_Flags = ADIOF_PERVOL;
  73.         (*ioa)->ioa_Request.io_Command = CMD_WRITE;
  74.         (*ioa)->ioa_Period = per;
  75.         (*ioa)->ioa_Volume = vol;
  76.  
  77.         /* For some reason, the Audio chip can't play samples */
  78.         /* longer than 131k, so we kludge.  Oh, well. */
  79.         if(len < 131000)
  80.             (*ioa)->ioa_Cycles = repeat;
  81.         else
  82.             (*ioa)->ioa_Cycles = 1;
  83.         }
  84.     }
  85.     }
  86. }
  87.  
  88. /*****************************************************************************
  89.  *               Purpose: To play back a sound.                 *
  90.  *****************************************************************************/
  91.  
  92. struct IOAudio *PlaySound(buffer, buflen, repeat, period, volume)
  93. BYTE *buffer;
  94. ULONG buflen;
  95. LONG repeat,period,volume;
  96. {
  97.     struct IOAudio *ioa;
  98.     BYTE *DataPtr;
  99.     ULONG PlayLen;
  100.  
  101.     DataPtr = buffer;
  102.  
  103.     /* Set Up IOAudio structure */
  104.     SetIOA(period, volume, repeat, buflen, &ioa);
  105.     if (!ioa)
  106.     return(NULL);
  107.  
  108.     /* Set up data and length pointers of ioa */
  109.     SetLength(&PlayLen, buflen, &DataPtr, ioa);
  110.  
  111.     /* Send command to Audio chip */
  112.     BeginIO(ioa);
  113.     repeat--;
  114.  
  115.     /* If no data remains to play, return ioa pointer */
  116.     if(PlayLen == 0)
  117.     return(ioa);
  118.  
  119.     /* If there is more (buflen > 131000), continue until there isn't */
  120.     while(TRUE)
  121.     {
  122.     ULONG signals;
  123.  
  124.     /* Wait until current chunk is done */
  125.     signals = Wait((1 << ioa->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C);
  126.  
  127.     if (signals & SIGBREAKF_CTRL_C)
  128.     {
  129.         SetSignal(SIGBREAKF_CTRL_C, SIGBREAKF_CTRL_C);
  130.         return(ioa);
  131.     }
  132.  
  133.     /* If more remains, continue */
  134.     if(PlayLen > 0)
  135.     {
  136.         /* update pointers and start next chunk */
  137.         FixLength(&PlayLen, &DataPtr, ioa);
  138.         BeginIO(ioa);
  139.         /* return if playing the last chunk for the last time */
  140.         if((PlayLen == 0) && (repeat == 0))
  141.         return(ioa);
  142.     }
  143.     /* If not ... */
  144.     else
  145.     {
  146.         /* Check repeat counter */
  147.         if(repeat != 0)
  148.         {
  149.         /* Restart wave */
  150.         DataPtr = buffer;
  151.         SetLength(&PlayLen, buflen, &DataPtr, ioa);
  152.         BeginIO(ioa);
  153.         if(repeat > 0)
  154.             repeat--;
  155.         }
  156.     }
  157.     }
  158. }
  159.  
  160. /*****************************************************************************
  161.  * Purpose: To stop and delete a sound. THIS IS THE CLEAN UP ROUTINE!!         *
  162.  *****************************************************************************/
  163.  
  164. StopSound(struct IOAudio *ioa)
  165. {
  166.     AbortIO(ioa);
  167.     if(ioa->ioa_Request.io_Device)
  168.     CloseDevice(ioa);
  169.     if(ioa->ioa_Request.io_Message.mn_ReplyPort)
  170.     DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
  171.     if(ioa)
  172.     FreeMem(ioa,sizeof(struct IOAudio));
  173. }
  174.  
  175. /*****************************************************************************
  176.  *       Purpose: To set the length of the sound to be played.         *
  177.  *****************************************************************************/
  178.  
  179. SetLength(ULONG *LenPtr, ULONG buflen, BYTE **DataHndl, struct IOAudio *ioa)
  180. {
  181.     if(buflen <= 131000)
  182.     (*LenPtr) = buflen;
  183.     else
  184.     (*LenPtr) = 131000;
  185.  
  186.     ioa->ioa_Length = (*LenPtr);
  187.     ioa->ioa_Data = (*DataHndl);
  188.  
  189.     if((*LenPtr) != buflen)
  190.     {
  191.     (*LenPtr) = buflen - 131000;
  192.     (*DataHndl) += 131000;
  193.     }
  194.     else
  195.     (*LenPtr) = 0;
  196. }
  197.  
  198. /*****************************************************************************
  199.  * Purpose: To Check, if the full sound is to be played (or max 131000 bytes)*
  200.  *****************************************************************************/
  201.  
  202. FixLength(ULONG *LenPtr, BYTE **DataHndl, struct IOAudio *ioa)
  203. {
  204.     if((*LenPtr) > 131000)
  205.     {
  206.     ioa->ioa_Length = 131000;
  207.     ioa->ioa_Data = (*DataHndl);
  208.     (*LenPtr) -= 131000;
  209.     (*DataHndl) += 131000;
  210.     }
  211.     else
  212.     {
  213.     ioa->ioa_Length = (*LenPtr);
  214.     ioa->ioa_Data = (*DataHndl);
  215.     (*LenPtr) = 0;
  216.     }
  217. }
  218.